home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / python2.4 / bsddb / dbtables.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2007-04-29  |  18.5 KB  |  714 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. _cvsid = '$Id: dbtables.py 36901 2004-08-08 00:54:21Z tim_one $'
  5. import re
  6. import sys
  7. import copy
  8. import xdrlib
  9. import random
  10. from types import ListType, StringType
  11. import cPickle as pickle
  12.  
  13. try:
  14.     from bsddb3.db import *
  15. except ImportError:
  16.     from bsddb.db import *
  17.  
  18.  
  19. class TableDBError(StandardError):
  20.     pass
  21.  
  22.  
  23. class TableAlreadyExists(TableDBError):
  24.     pass
  25.  
  26.  
  27. class Cond:
  28.     '''This condition matches everything'''
  29.     
  30.     def __call__(self, s):
  31.         return 1
  32.  
  33.  
  34.  
  35. class ExactCond(Cond):
  36.     '''Acts as an exact match condition function'''
  37.     
  38.     def __init__(self, strtomatch):
  39.         self.strtomatch = strtomatch
  40.  
  41.     
  42.     def __call__(self, s):
  43.         return s == self.strtomatch
  44.  
  45.  
  46.  
  47. class PrefixCond(Cond):
  48.     '''Acts as a condition function for matching a string prefix'''
  49.     
  50.     def __init__(self, prefix):
  51.         self.prefix = prefix
  52.  
  53.     
  54.     def __call__(self, s):
  55.         return s[:len(self.prefix)] == self.prefix
  56.  
  57.  
  58.  
  59. class PostfixCond(Cond):
  60.     '''Acts as a condition function for matching a string postfix'''
  61.     
  62.     def __init__(self, postfix):
  63.         self.postfix = postfix
  64.  
  65.     
  66.     def __call__(self, s):
  67.         return s[-len(self.postfix):] == self.postfix
  68.  
  69.  
  70.  
  71. class LikeCond(Cond):
  72.     """
  73.     Acts as a function that will match using an SQL 'LIKE' style
  74.     string.  Case insensitive and % signs are wild cards.
  75.     This isn't perfect but it should work for the simple common cases.
  76.     """
  77.     
  78.     def __init__(self, likestr, re_flags = re.IGNORECASE):
  79.         chars_to_escape = '.*+()[]?'
  80.         for char in chars_to_escape:
  81.             likestr = likestr.replace(char, '\\' + char)
  82.         
  83.         self.likestr = likestr.replace('%', '.*')
  84.         self.re = re.compile('^' + self.likestr + '$', re_flags)
  85.  
  86.     
  87.     def __call__(self, s):
  88.         return self.re.match(s)
  89.  
  90.  
  91. _table_names_key = '__TABLE_NAMES__'
  92. _columns = '._COLUMNS__'
  93.  
  94. def _columns_key(table):
  95.     return table + _columns
  96.  
  97. _data = '._DATA_.'
  98. _rowid = '._ROWID_.'
  99. _rowid_str_len = 8
  100.  
  101. def _data_key(table, col, rowid):
  102.     return table + _data + col + _data + rowid
  103.  
  104.  
  105. def _search_col_data_key(table, col):
  106.     return table + _data + col + _data
  107.  
  108.  
  109. def _search_all_data_key(table):
  110.     return table + _data
  111.  
  112.  
  113. def _rowid_key(table, rowid):
  114.     return table + _rowid + rowid + _rowid
  115.  
  116.  
  117. def _search_rowid_key(table):
  118.     return table + _rowid
  119.  
  120.  
  121. def contains_metastrings(s):
  122.     '''Verify that the given string does not contain any
  123.     metadata strings that might interfere with dbtables database operation.
  124.     '''
  125.     if s.find(_table_names_key) >= 0 and s.find(_columns) >= 0 and s.find(_data) >= 0 or s.find(_rowid) >= 0:
  126.         return 1
  127.     else:
  128.         return 0
  129.  
  130.  
  131. class bsdTableDB:
  132.     
  133.     def __init__(self, filename, dbhome, create = 0, truncate = 0, mode = 384, recover = 0, dbflags = 0):
  134.         '''bsdTableDB.open(filename, dbhome, create=0, truncate=0, mode=0600)
  135.         Open database name in the dbhome BerkeleyDB directory.
  136.         Use keyword arguments when calling this constructor.
  137.         '''
  138.         self.db = None
  139.         myflags = DB_THREAD
  140.         if create:
  141.             myflags |= DB_CREATE
  142.         
  143.         flagsforenv = DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN | dbflags
  144.         
  145.         try:
  146.             dbflags |= DB_AUTO_COMMIT
  147.         except AttributeError:
  148.             pass
  149.  
  150.         if recover:
  151.             flagsforenv = flagsforenv | DB_RECOVER
  152.         
  153.         self.env = DBEnv()
  154.         self.env.set_lk_detect(DB_LOCK_DEFAULT)
  155.         self.env.open(dbhome, myflags | flagsforenv)
  156.         if truncate:
  157.             myflags |= DB_TRUNCATE
  158.         
  159.         self.db = DB(self.env)
  160.         self.db.set_get_returns_none(1)
  161.         self.db.set_flags(DB_DUP)
  162.         self.db.open(filename, DB_BTREE, dbflags | myflags, mode)
  163.         self.dbfilename = filename
  164.         txn = self.env.txn_begin()
  165.         
  166.         try:
  167.             if not self.db.has_key(_table_names_key, txn):
  168.                 self.db.put(_table_names_key, pickle.dumps([], 1), txn = txn)
  169.         except:
  170.             txn.abort()
  171.             raise 
  172.  
  173.         txn.commit()
  174.         self._bsdTableDB__tablecolumns = { }
  175.  
  176.     
  177.     def __del__(self):
  178.         self.close()
  179.  
  180.     
  181.     def close(self):
  182.         if self.db is not None:
  183.             self.db.close()
  184.             self.db = None
  185.         
  186.         if self.env is not None:
  187.             self.env.close()
  188.             self.env = None
  189.         
  190.  
  191.     
  192.     def checkpoint(self, mins = 0):
  193.         
  194.         try:
  195.             self.env.txn_checkpoint(mins)
  196.         except DBIncompleteError:
  197.             pass
  198.  
  199.  
  200.     
  201.     def sync(self):
  202.         
  203.         try:
  204.             self.db.sync()
  205.         except DBIncompleteError:
  206.             pass
  207.  
  208.  
  209.     
  210.     def _db_print(self):
  211.         '''Print the database to stdout for debugging'''
  212.         print '******** Printing raw database for debugging ********'
  213.         cur = self.db.cursor()
  214.         
  215.         try:
  216.             (key, data) = cur.first()
  217.             while None:
  218.                 print repr({
  219.                     key: data })
  220.                 next = cur.next()
  221.                 if next:
  222.                     (key, data) = next
  223.                     continue
  224.                 cur.close()
  225.                 return None
  226.         except DBNotFoundError:
  227.             cur.close()
  228.  
  229.  
  230.     
  231.     def CreateTable(self, table, columns):
  232.         '''CreateTable(table, columns) - Create a new table in the database
  233.         raises TableDBError if it already exists or for other DB errors.
  234.         '''
  235.         if not isinstance(columns, ListType):
  236.             raise AssertionError
  237.         txn = None
  238.         
  239.         try:
  240.             if contains_metastrings(table):
  241.                 raise ValueError('bad table name: contains reserved metastrings')
  242.             
  243.             for column in columns:
  244.                 if contains_metastrings(column):
  245.                     raise ValueError('bad column name: contains reserved metastrings')
  246.                     continue
  247.             
  248.             columnlist_key = _columns_key(table)
  249.             if self.db.has_key(columnlist_key):
  250.                 raise TableAlreadyExists, 'table already exists'
  251.             
  252.             txn = self.env.txn_begin()
  253.             self.db.put(columnlist_key, pickle.dumps(columns, 1), txn = txn)
  254.             tablelist = pickle.loads(self.db.get(_table_names_key, txn = txn, flags = DB_RMW))
  255.             tablelist.append(table)
  256.             self.db.delete(_table_names_key, txn)
  257.             self.db.put(_table_names_key, pickle.dumps(tablelist, 1), txn = txn)
  258.             txn.commit()
  259.             txn = None
  260.         except DBError:
  261.             dberror = None
  262.             if txn:
  263.                 txn.abort()
  264.             
  265.             raise TableDBError, dberror[1]
  266.  
  267.  
  268.     
  269.     def ListTableColumns(self, table):
  270.         """Return a list of columns in the given table.
  271.         [] if the table doesn't exist.
  272.         """
  273.         if not isinstance(table, StringType):
  274.             raise AssertionError
  275.         if contains_metastrings(table):
  276.             raise ValueError, 'bad table name: contains reserved metastrings'
  277.         
  278.         columnlist_key = _columns_key(table)
  279.         if not self.db.has_key(columnlist_key):
  280.             return []
  281.         
  282.         pickledcolumnlist = self.db.get(columnlist_key)
  283.         if pickledcolumnlist:
  284.             return pickle.loads(pickledcolumnlist)
  285.         else:
  286.             return []
  287.  
  288.     
  289.     def ListTables(self):
  290.         '''Return a list of tables in this database.'''
  291.         pickledtablelist = self.db.get(_table_names_key)
  292.         if pickledtablelist:
  293.             return pickle.loads(pickledtablelist)
  294.         else:
  295.             return []
  296.  
  297.     
  298.     def CreateOrExtendTable(self, table, columns):
  299.         '''CreateOrExtendTable(table, columns)
  300.  
  301.         - Create a new table in the database.
  302.         If a table of this name already exists, extend it to have any
  303.         additional columns present in the given list as well as
  304.         all of its current columns.
  305.         '''
  306.         if not isinstance(columns, ListType):
  307.             raise AssertionError
  308.         
  309.         try:
  310.             self.CreateTable(table, columns)
  311.         except TableAlreadyExists:
  312.             txn = None
  313.             
  314.             try:
  315.                 columnlist_key = _columns_key(table)
  316.                 txn = self.env.txn_begin()
  317.                 oldcolumnlist = pickle.loads(self.db.get(columnlist_key, txn = txn, flags = DB_RMW))
  318.                 oldcolumnhash = { }
  319.                 for c in oldcolumnlist:
  320.                     oldcolumnhash[c] = c
  321.                 
  322.                 newcolumnlist = copy.copy(oldcolumnlist)
  323.                 for c in columns:
  324.                     if not oldcolumnhash.has_key(c):
  325.                         newcolumnlist.append(c)
  326.                         continue
  327.                 
  328.                 if newcolumnlist != oldcolumnlist:
  329.                     self.db.delete(columnlist_key, txn)
  330.                     self.db.put(columnlist_key, pickle.dumps(newcolumnlist, 1), txn = txn)
  331.                 
  332.                 txn.commit()
  333.                 txn = None
  334.                 self._bsdTableDB__load_column_info(table)
  335.             except DBError:
  336.                 dberror = None
  337.                 if txn:
  338.                     txn.abort()
  339.                 
  340.                 raise TableDBError, dberror[1]
  341.             except:
  342.                 None<EXCEPTION MATCH>DBError
  343.             
  344.  
  345.             None<EXCEPTION MATCH>DBError
  346.  
  347.  
  348.     
  349.     def __load_column_info(self, table):
  350.         '''initialize the self.__tablecolumns dict'''
  351.         
  352.         try:
  353.             tcolpickles = self.db.get(_columns_key(table))
  354.         except DBNotFoundError:
  355.             raise TableDBError, 'unknown table: %r' % (table,)
  356.  
  357.         if not tcolpickles:
  358.             raise TableDBError, 'unknown table: %r' % (table,)
  359.         
  360.         self._bsdTableDB__tablecolumns[table] = pickle.loads(tcolpickles)
  361.  
  362.     
  363.     def __new_rowid(self, table, txn):
  364.         '''Create a new unique row identifier'''
  365.         unique = 0
  366.         while not unique:
  367.             p = xdrlib.Packer()
  368.             p.pack_int(int(random.random() * 2147483647))
  369.             p.pack_int(int(random.random() * 2147483647))
  370.             newid = p.get_buffer()
  371.             
  372.             try:
  373.                 self.db.put(_rowid_key(table, newid), None, txn = txn, flags = DB_NOOVERWRITE)
  374.             except DBKeyExistError:
  375.                 continue
  376.  
  377.             unique = 1
  378.         return newid
  379.  
  380.     
  381.     def Insert(self, table, rowdict):
  382.         '''Insert(table, datadict) - Insert a new row into the table
  383.         using the keys+values from rowdict as the column values.
  384.         '''
  385.         txn = None
  386.         
  387.         try:
  388.             if not self.db.has_key(_columns_key(table)):
  389.                 raise TableDBError, 'unknown table'
  390.             
  391.             if not self._bsdTableDB__tablecolumns.has_key(table):
  392.                 self._bsdTableDB__load_column_info(table)
  393.             
  394.             for column in rowdict.keys():
  395.                 if not self._bsdTableDB__tablecolumns[table].count(column):
  396.                     raise TableDBError, 'unknown column: %r' % (column,)
  397.                     continue
  398.             
  399.             txn = self.env.txn_begin()
  400.             rowid = self._bsdTableDB__new_rowid(table, txn = txn)
  401.             for column, dataitem in rowdict.items():
  402.                 self.db.put(_data_key(table, column, rowid), dataitem, txn = txn)
  403.             
  404.             txn.commit()
  405.             txn = None
  406.         except DBError:
  407.             dberror = None
  408.             info = sys.exc_info()
  409.             if txn:
  410.                 txn.abort()
  411.                 self.db.delete(_rowid_key(table, rowid))
  412.             
  413.             raise TableDBError, dberror[1], info[2]
  414.  
  415.  
  416.     
  417.     def Modify(self, table, conditions = { }, mappings = { }):
  418.         """Modify(table, conditions) - Modify in rows matching 'conditions'
  419.         using mapping functions in 'mappings'
  420.         * conditions is a dictionary keyed on column names
  421.         containing condition functions expecting the data string as an
  422.         argument and returning a boolean.
  423.         * mappings is a dictionary keyed on column names containint condition
  424.         functions expecting the data string as an argument and returning the
  425.         new string for that column.
  426.         """
  427.         
  428.         try:
  429.             matching_rowids = self._bsdTableDB__Select(table, [], conditions)
  430.             columns = mappings.keys()
  431.             for rowid in matching_rowids.keys():
  432.                 txn = None
  433.                 
  434.                 try:
  435.                     for column in columns:
  436.                         txn = self.env.txn_begin()
  437.                         
  438.                         try:
  439.                             dataitem = self.db.get(_data_key(table, column, rowid), txn)
  440.                             self.db.delete(_data_key(table, column, rowid), txn)
  441.                         except DBNotFoundError:
  442.                             dataitem = None
  443.  
  444.                         dataitem = mappings[column](dataitem)
  445.                         if dataitem != None:
  446.                             self.db.put(_data_key(table, column, rowid), dataitem, txn = txn)
  447.                         
  448.                         txn.commit()
  449.                         txn = None
  450.                 continue
  451.                 except DBError:
  452.                     dberror = None
  453.                     if txn:
  454.                         txn.abort()
  455.                     
  456.                     raise 
  457.                     continue
  458.                 
  459.  
  460.         except DBError:
  461.             dberror = None
  462.             raise TableDBError, dberror[1]
  463.  
  464.  
  465.     
  466.     def Delete(self, table, conditions = { }):
  467.         '''Delete(table, conditions) - Delete items matching the given
  468.         conditions from the table.
  469.         * conditions is a dictionary keyed on column names
  470.         containing condition functions expecting the data string as an
  471.         argument and returning a boolean.
  472.         '''
  473.         
  474.         try:
  475.             matching_rowids = self._bsdTableDB__Select(table, [], conditions)
  476.             columns = self._bsdTableDB__tablecolumns[table]
  477.             for rowid in matching_rowids.keys():
  478.                 txn = None
  479.                 
  480.                 try:
  481.                     txn = self.env.txn_begin()
  482.                     for column in columns:
  483.                         
  484.                         try:
  485.                             self.db.delete(_data_key(table, column, rowid), txn)
  486.                         continue
  487.                         except DBNotFoundError:
  488.                             continue
  489.                         
  490.  
  491.                     
  492.                     
  493.                     try:
  494.                         self.db.delete(_rowid_key(table, rowid), txn)
  495.                     except DBNotFoundError:
  496.                         None<EXCEPTION MATCH>DBNotFoundError
  497.                         None<EXCEPTION MATCH>DBNotFoundError
  498.                     except:
  499.                         None<EXCEPTION MATCH>DBNotFoundError
  500.  
  501.                     txn.commit()
  502.                     txn = None
  503.                 continue
  504.                 except DBError:
  505.                     dberror = None
  506.                     if txn:
  507.                         txn.abort()
  508.                     
  509.                     raise 
  510.                     continue
  511.                 
  512.  
  513.         except DBError:
  514.             dberror = None
  515.             raise TableDBError, dberror[1]
  516.  
  517.  
  518.     
  519.     def Select(self, table, columns, conditions = { }):
  520.         '''Select(table, conditions) - retrieve specific row data
  521.         Returns a list of row column->value mapping dictionaries.
  522.         * columns is a list of which column data to return.  If
  523.           columns is None, all columns will be returned.
  524.         * conditions is a dictionary keyed on column names
  525.           containing callable conditions expecting the data string as an
  526.           argument and returning a boolean.
  527.         '''
  528.         
  529.         try:
  530.             if not self._bsdTableDB__tablecolumns.has_key(table):
  531.                 self._bsdTableDB__load_column_info(table)
  532.             
  533.             if columns is None:
  534.                 columns = self._bsdTableDB__tablecolumns[table]
  535.             
  536.             matching_rowids = self._bsdTableDB__Select(table, columns, conditions)
  537.         except DBError:
  538.             dberror = None
  539.             raise TableDBError, dberror[1]
  540.  
  541.         return matching_rowids.values()
  542.  
  543.     
  544.     def __Select(self, table, columns, conditions):
  545.         '''__Select() - Used to implement Select and Delete (above)
  546.         Returns a dictionary keyed on rowids containing dicts
  547.         holding the row data for columns listed in the columns param
  548.         that match the given conditions.
  549.         * conditions is a dictionary keyed on column names
  550.         containing callable conditions expecting the data string as an
  551.         argument and returning a boolean.
  552.         '''
  553.         if not self._bsdTableDB__tablecolumns.has_key(table):
  554.             self._bsdTableDB__load_column_info(table)
  555.         
  556.         if columns is None:
  557.             columns = self.tablecolumns[table]
  558.         
  559.         for column in columns + conditions.keys():
  560.             if not self._bsdTableDB__tablecolumns[table].count(column):
  561.                 raise TableDBError, 'unknown column: %r' % (column,)
  562.                 continue
  563.         
  564.         matching_rowids = { }
  565.         rejected_rowids = { }
  566.         
  567.         def cmp_conditions(atuple, btuple):
  568.             a = atuple[1]
  569.             b = btuple[1]
  570.             if type(a) is type(b):
  571.                 if isinstance(a, PrefixCond) and isinstance(b, PrefixCond):
  572.                     return cmp(len(b.prefix), len(a.prefix))
  573.                 
  574.                 if isinstance(a, LikeCond) and isinstance(b, LikeCond):
  575.                     return cmp(len(b.likestr), len(a.likestr))
  576.                 
  577.                 return 0
  578.             
  579.             if isinstance(a, ExactCond):
  580.                 return -1
  581.             
  582.             if isinstance(b, ExactCond):
  583.                 return 1
  584.             
  585.             if isinstance(a, PrefixCond):
  586.                 return -1
  587.             
  588.             if isinstance(b, PrefixCond):
  589.                 return 1
  590.             
  591.             return 0
  592.  
  593.         conditionlist = conditions.items()
  594.         conditionlist.sort(cmp_conditions)
  595.         cur = self.db.cursor()
  596.         column_num = -1
  597.         for column, condition in conditionlist:
  598.             column_num = column_num + 1
  599.             searchkey = _search_col_data_key(table, column)
  600.             if column in columns:
  601.                 savethiscolumndata = 1
  602.             else:
  603.                 savethiscolumndata = 0
  604.             
  605.             try:
  606.                 (key, data) = cur.set_range(searchkey)
  607.                 while key[:len(searchkey)] == searchkey:
  608.                     rowid = key[-_rowid_str_len:]
  609.                     if not rejected_rowids.has_key(rowid):
  610.                         if not condition or condition(data):
  611.                             if not matching_rowids.has_key(rowid):
  612.                                 matching_rowids[rowid] = { }
  613.                             
  614.                             if savethiscolumndata:
  615.                                 matching_rowids[rowid][column] = data
  616.                             
  617.                         elif matching_rowids.has_key(rowid):
  618.                             del matching_rowids[rowid]
  619.                         
  620.                         rejected_rowids[rowid] = rowid
  621.                     
  622.                     (key, data) = cur.next()
  623.             continue
  624.             except DBError:
  625.                 dberror = None
  626.                 if dberror[0] != DB_NOTFOUND:
  627.                     raise 
  628.                     continue
  629.                 continue
  630.                 continue
  631.             
  632.  
  633.         
  634.         cur.close()
  635.         del rejected_rowids
  636.         if len(columns) > 0:
  637.             for rowid, rowdata in matching_rowids.items():
  638.                 for column in columns:
  639.                     if rowdata.has_key(column):
  640.                         continue
  641.                     
  642.                     
  643.                     try:
  644.                         rowdata[column] = self.db.get(_data_key(table, column, rowid))
  645.                     continue
  646.                     except DBError:
  647.                         dberror = None
  648.                         if dberror[0] != DB_NOTFOUND:
  649.                             raise 
  650.                         
  651.                         rowdata[column] = None
  652.                         continue
  653.                     
  654.  
  655.                 
  656.             
  657.         
  658.         return matching_rowids
  659.  
  660.     
  661.     def Drop(self, table):
  662.         '''Remove an entire table from the database'''
  663.         txn = None
  664.         
  665.         try:
  666.             txn = self.env.txn_begin()
  667.             self.db.delete(_columns_key(table), txn)
  668.             cur = self.db.cursor(txn)
  669.             table_key = _search_all_data_key(table)
  670.             while None:
  671.                 
  672.                 try:
  673.                     (key, data) = cur.set_range(table_key)
  674.                 except DBNotFoundError:
  675.                     break
  676.  
  677.                 if key[:len(table_key)] != table_key:
  678.                     break
  679.                 
  680.             table_key = _search_rowid_key(table)
  681.             while None:
  682.                 
  683.                 try:
  684.                     (key, data) = cur.set_range(table_key)
  685.                 except DBNotFoundError:
  686.                     break
  687.  
  688.                 if key[:len(table_key)] != table_key:
  689.                     break
  690.                 
  691.             cur.close()
  692.             tablelist = pickle.loads(self.db.get(_table_names_key, txn = txn, flags = DB_RMW))
  693.             
  694.             try:
  695.                 tablelist.remove(table)
  696.             except ValueError:
  697.                 pass
  698.  
  699.             self.db.delete(_table_names_key, txn)
  700.             self.db.put(_table_names_key, pickle.dumps(tablelist, 1), txn = txn)
  701.             txn.commit()
  702.             txn = None
  703.             if self._bsdTableDB__tablecolumns.has_key(table):
  704.                 del self._bsdTableDB__tablecolumns[table]
  705.         except DBError:
  706.             dberror = None
  707.             if txn:
  708.                 txn.abort()
  709.             
  710.             raise TableDBError, dberror[1]
  711.  
  712.  
  713.  
  714.